﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using Microsoft.Practices.ServiceLocation;
using CreatureSoft.Hoot.Web.IoC;
using CreatureSoft.Hoot.Data.Infrastructure;
using CreatureSoft.Hoot.Data.Repositories;
using CreatureSoft.Hoot.Service.DocumentManagent;
using System.Configuration;
using System.Runtime.ExceptionServices;
using AutoMapper;
using CreatureSoft.Hoot.Domain.DocumentManagent;
using CreatureSoft.Hoot.Web.Models;
using CreatureSoft.Hoot.Web.Security;
using CreatureSoft.Hoot.Service.Security;

namespace CreatureSoft.Hoot.Web
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        string _item = "__RequestExceptionKey";

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");


            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                new string[] { "Hoot.Web.Controllers" }
                // Parameter defaults
            );

        }
        
        protected void Application_Start()
        {
            SetupMonitoring();

            AreaRegistration.RegisterAllAreas();
            
            RegisterGlobalFilters(GlobalFilters.Filters);
            RegisterRoutes(RouteTable.Routes);
            IUnityContainer container = GetUnityContainer();
            var serviceLocator = new UnityServiceLocator(container);
            ServiceLocator.SetLocatorProvider(() => serviceLocator);
            DependencyResolver.SetResolver(new UnityDependencyResolver(container));
            
            ConfigureAutoMapping();            
        }

        //TODO : Refactor into seperate Mapping Class (ConfigureAutoMapping).
        private void ConfigureAutoMapping()
        {
            //Mapper.CreateMap<Folder, FolderViewModel>().ForMember(dest => dest.ParentId, opt => opt.MapFrom(src => src.ParentFolderId));
            //Mapper.CreateMap<FolderViewModel, Folder>().ForMember(dest => dest.ParentFolderId, opt => opt.MapFrom(src => src.ParentId));
            Mapper.CreateMap<FolderModel, Folder>();
            Mapper.CreateMap<Folder, FolderModel>();
        }

        //TODO : Refactor into seperate Mapping Class (GetUnityContainer).
        private IUnityContainer GetUnityContainer()
        {
            //Create UnityContainer          
            IUnityContainer container = new UnityContainer()

            .RegisterType<IDatabaseFactory, DatabaseFactory>(new HttpContextLifetimeManager<IDatabaseFactory>())
            .RegisterType<IUnitOfWork, UnitOfWork>(new HttpContextLifetimeManager<IUnitOfWork>())

            //Repositories
            .RegisterType<IFolderRepository, FolderRepository>(new HttpContextLifetimeManager<IFolderRepository>())
            .RegisterType<IUserRepository, UserRepository>(new HttpContextLifetimeManager<IUserRepository>())

            //Services
            .RegisterType<IFolderService, FolderService>(new HttpContextLifetimeManager<IFolderService>())
            .RegisterType<IUserService, UserService>(new HttpContextLifetimeManager<IUserService>())

            .RegisterType<IHootMembershipProvider, HootMembershipProvider>(new HttpContextLifetimeManager<IHootMembershipProvider>());

            
            //container.RegisterType<IMembershipProvider, CustomMembershipProvider>(new InjectionProperty(new ResolvedParameter<IProveaRepository>()))
            return container;
        }

        //TODO : Refactor into seperate Mapping Class (SetupMonitoring).
        private void SetupMonitoring()
        {
            bool appDomainMonitoringEnabled, firstChanceExceptionMonitoringEnabled;
            bool.TryParse(ConfigurationManager.AppSettings["AppDomainMonitoringEnabled"], out appDomainMonitoringEnabled);
            bool.TryParse(ConfigurationManager.AppSettings["FirstChanceExceptionMonitoringEnabled"], out firstChanceExceptionMonitoringEnabled);
            if (appDomainMonitoringEnabled)
            {
                AppDomain.MonitoringIsEnabled = true;
            }
            if (firstChanceExceptionMonitoringEnabled)
            {
                AppDomain.CurrentDomain.FirstChanceException += (object source, FirstChanceExceptionEventArgs e) =>
                {
                    if (HttpContext.Current == null)// If no context available, ignore it
                        return;
                    if (HttpContext.Current.Items[_item] == null)
                        HttpContext.Current.Items[_item] = new RequestException { Exceptions = new List<Exception>() };
                    (HttpContext.Current.Items[_item] as RequestException).Exceptions.Add(e.Exception);
                };
            }
        }

        protected void Application_EndRequest()
        {
            if (Context.Items[_item] != null)
            {
                //Only add the request if atleast one exception is raised
                var reqExc = Context.Items[_item] as RequestException;
                reqExc.Url = Request.Url.AbsoluteUri;
                Application.Lock();
                if (Application["AllExc"] == null)
                    Application["AllExc"] = new List<RequestException>();
                (Application["AllExc"] as List<RequestException>).Add(reqExc);
                Application.UnLock();
            }
        }

    }


}